/**
 * Beschreiben Sie hier die Klasse Baumaschine.
 * 
 * @author christoph.stueber@mes-alsfeld.de
 * @version Schuljahr 2013/2014 erstellt 15.03.2014 geändert 29.03.2014
 */
public class Baumaschine
{
    /** */
    private int maschinenZaehler = 0;

    /** */
    private int maschinenNr;

    /** */
    private String bezeichnung;

    /** */
    private MaschinenTyp typ;

    /** */
    private Buchung ersteBuchung;

    /**
     * Konstruktor für Objekte der Klasse Baumaschine.
     * 
     * @param typ String mit der Typ-Bezeichnung.
     * @param bezeichnung String mit der Bezeichnung
     * @param ppt double der Preis pro tag
     */
    public Baumaschine(MaschinenTyp typ, String bezeichnung)
    {
	++maschinenZaehler;
	setMaschinenNummer(maschinenZaehler);
	this.typ = typ;
	this.setBezeichnung(bezeichnung);
	typ.hinzufuegenBaumaschine(this);
    }

    public Buchung buche(Auftrag a, Datum von, Datum bis)
    {
	Buchung neueBuchung = null;
	if (istFrei(von, bis))
	{
	    // leere Liste
	    if (ersteBuchung == null)
	    {
		neueBuchung = new Buchung(a, this, von, bis, null);
		ersteBuchung = neueBuchung;
	    }
	    else
	    {
		if (bis.vergleicheMit(ersteBuchung.getVonDatum()) < 0)
		{
		    // Listenanfang
		    neueBuchung = new Buchung(a, this, von, bis, ersteBuchung);
		    ersteBuchung = neueBuchung;
		}
		else
		{
		    Buchung aktuelle = ersteBuchung;
		    // Einfügestelle suchen
		    while ((von.vergleicheMit(aktuelle.getBisDatum()) > 0)
			    && (neueBuchung == null))
		    {
			if (aktuelle.getNaechste() != null)
			{
			    if (bis.vergleicheMit(aktuelle.getNaechste()
				    .getVonDatum()) < 0)
			    {
				// Listenmitte
				neueBuchung = new Buchung(a, this, von, bis,
					aktuelle.getNaechste());
				aktuelle.setNaechste(neueBuchung);
			    }
			    else
			    {
				aktuelle = aktuelle.getNaechste();
			    }
			}
			else
			{
			    // am Listenende angekommen
			    neueBuchung = new Buchung(a, this, von, bis, null);
			    aktuelle.setNaechste(neueBuchung);
			}

		    }
		}
	    }
	}
	return neueBuchung;
    }

    /**
     * Ergibt einen Wahrheitswert true wenn die Baumaschine in dem Interval
     * von/bis nicht mit einer Buchung belegt ist.
     * 
     * @param von Datum
     * @param bis Datum
     * @return boolean wahl wenn die Bauaschine frei ist
     */
    public boolean istFrei(Datum von, Datum bis)
    {
	boolean frei = false;
	if (ersteBuchung == null)
	{
	    frei = true;
	}
	else
	{
	    if (bis.vergleicheMit(ersteBuchung.getVonDatum()) < 0)
	    {
		// System.out.println("Bis     " + bis.toSQLString());
		// System.out.println("Frei ab " +
		// ersteBuchung.getVonDatum().toSQLString());
		// System.out.println(bis.vergleicheMit(ersteBuchung.getVonDatum()));
		frei = true;
	    }
	    else
	    {
		Buchung aktuelle = ersteBuchung;
		while ((von.vergleicheMit(aktuelle.getBisDatum()) > 0) && !frei)
		{
		    if (aktuelle.getNaechste() != null)
		    {
			if (bis.vergleicheMit(aktuelle.getNaechste()
				.getVonDatum()) < 0)
			{
			    frei = true;
			}
			else
			{
			    aktuelle = aktuelle.getNaechste();
			}
		    }
		    else
		    {
			// am Ende angekommen
			frei = true;
		    }
		}
	    }
	}
	return frei;
    }

    /**
     * toString-Methode
     */
    public String toString()
    {
	StringBuilder b = new StringBuilder();
	b.append(typ).append("\n");
	Buchung aktuelle = ersteBuchung;
	while (aktuelle != null)
	{
	    b.append("- ");
	    b.append(aktuelle.toString()).append("\n");
	    aktuelle = aktuelle.getNaechste();
	}
	return b.toString();
    }

    /**
     * @return the maschinenNr
     */
    public int getMaschinenNummer()
    {
	return maschinenNr;
    }

    /**
     * @param maschinenNr the maschinenNr to set
     */
    public void setMaschinenNummer(int maschinenNr)
    {
	this.maschinenNr = maschinenNr;
    }

    /**
     * @return the bezeichnung
     */
    public String getBezeichnung()
    {
	return bezeichnung;
    }

    /**
     * @param bezeichnung the bezeichnung to set
     */
    public void setBezeichnung(String bezeichnung)
    {
	this.bezeichnung = bezeichnung;
    }

    /**
     * @return the typ
     */
    public MaschinenTyp getTyp()
    {
	return typ;
    }

    /**
     * @param typ the typ to set
     */
    public void setTyp(MaschinenTyp typ)
    {
	this.typ = typ;
    }

}
